package com.kgc.itrip.service.impl;

import com.alibaba.fastjson.JSON;
import com.kgc.itrip.common.Constants;
import com.kgc.itrip.common.MD5;
import com.kgc.itrip.common.UserAgentUtil;
import com.kgc.itrip.component.RedisTools;
import com.kgc.itrip.component.ValidationToken;
import com.kgc.itrip.exception.TokenValidationFailedException;
import com.kgc.itrip.pojo.ItripUser;
import com.kgc.itrip.service.TokenService;
import cz.mallat.uasparser.UserAgentInfo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Token管理接口相关业务服务实现
 * 
 * @author hduser
 *
 */
@Slf4j
@Data
@Service("tokenService")
public class TokenServiceImpl implements TokenService {

	/**
	 * 调用RedisAPI
	 */
	@Resource
	private RedisTools redisTools;
	@Resource
	private ValidationToken validationToken;

	private int expire = Constants.SESSION_TIMEOUT;// 2h
	private String tokenPrefix = "token:";//统一加入 token前缀标识

	/***
	 * @param agent Http头中的user-agent信息
	 * @param user 用户信息
	 * @return Token格式<br/>
	 * 	PC：“前缀PC-USERCODE-USERID-CREATIONDATE-RONDEM[6位]” 
	 *  <br/>
	 *  Android：“前缀ANDROID-USERCODE-USERID-CREATIONDATE-RONDEM[6位]”
	 */
	@Override
	public String generateToken(String agent, ItripUser user) {
		// TODO Auto-generated method stub
		try {
			UserAgentInfo userAgentInfo = UserAgentUtil.getUasParser().parse(agent);
			StringBuilder sb = new StringBuilder();
			sb.append(tokenPrefix);//统一前缀
			if (userAgentInfo.getDeviceType().equals(UserAgentInfo.UNKNOWN)) {
				if (UserAgentUtil.CheckAgent(agent)) {
					sb.append("MOBILE-");
				} else {
					sb.append("PC-");
				}
			} else if (userAgentInfo.getDeviceType()
					.equals("Personal computer")) {
				sb.append("PC-");
			} else
				sb.append("MOBILE-");
			//拼接结束后 token:MOBILE- 或者 是token:PC-
//			sb.append(user.getUserCode() + "-");
			sb.append(MD5.getMd5(user.getUserCode(),32) + "-");//加密用户名称
			sb.append(user.getId() + "-");
			sb.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
					+ "-");
			sb.append(MD5.getMd5(agent, 6));// 识别客户端的简化实现——6位MD5码
			//token:PC-3066014fa0b10792e4a762-23-20170531133947-4f6496
			return sb.toString();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void save(String token, ItripUser user) {
		if (token.startsWith(tokenPrefix+"PC-"))  //如果是PC端的token,2小时过期
			redisTools.set(token,user,expire);
		else   //如果是移动端的token,永不过期
			redisTools.set(token, JSON.toJSONString(user));// 手机认证信息永不失效
	}

	@Override
	public ItripUser load(String token) {		
		return validationToken.getCurrentUser(token);
	}

	@Override
	public void delete(String token) {
		if (redisTools.get(token)!=null){
			redisTools.del(token);
		}
	}



	@Override
	public String replaceToken(String agent, String token)
			throws TokenValidationFailedException {
		// 验证旧token是否有效
		if (!validate(agent,token)) {// token不存在
			throw new TokenValidationFailedException("未知的token或 token已过期");// 终止置换
		}
		Date TokenGenTime;// token生成时间
		try {//token:PC-3066014fa0b10792e4a762-23-20170531133947-4f6496
			String[] tokenDetails = token.split("-");
			SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
			TokenGenTime = formatter.parse(tokenDetails[3]);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			//log.error(e);
			throw new TokenValidationFailedException("token格式错误:" + token);
		}

		/*long passed = Calendar.getInstance().getTimeInMillis()  //12:00-11:30
				- TokenGenTime.getTime();// token已产生时间
		if (passed < REPLACEMENT_PROTECTION_TIMEOUT * 1000) {// 置换保护期内
			throw new TokenValidationFailedException("token处于置换保护期内，剩余"
					+ (REPLACEMENT_PROTECTION_TIMEOUT * 1000 - passed) / 1000
					+ "(s),禁止置换");
		}*/
		// 置换token
		String newToken = "";
		ItripUser user = this.load(token);
		long ttl = redisTools.getExpire(token);// token有效期（剩余秒数 ）
		if (ttl > 0 || ttl == -1) {// 兼容手机与PC端的token在有效期
			newToken = this.generateToken(agent, user);
			this.save(newToken, user);// 缓存新token
			redisTools.set(token, user,this.REPLACEMENT_DELAY);// 2分钟后旧token过期，注意手机端由永久有效变为2分钟（REPLACEMENT_DELAY默认值）后失效
		} else {// 其它未考虑情况，不予置换
			throw new TokenValidationFailedException("当前token的过期时间异常,禁止置换");
		}
		return newToken;
	}

	@Override
	public boolean validate(String agent, String token) {
		return validationToken.validate(agent,token);
	}


}
